package com.zxy.controlcenter.core.shiro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoleilu.hutool.convert.Convert;
import com.zxy.controlcenter.core.datasource.DBTypeEnum;
import com.zxy.controlcenter.core.datasource.TargetDataSource;
import com.zxy.controlcenter.core.shiro.ShiroKit;
import com.zxy.controlcenter.core.shiro.ShiroUser;
import com.zxy.controlcenter.core.shiro.service.UserAuthService;
import com.zxy.controlcenter.core.utils.ConstantFactory;
import com.zxy.controlcenter.core.http.SpringContextHolder;
import com.zxy.controlcenter.modular.system.model.Admin;
import com.zxy.controlcenter.modular.system.repository.AdminMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zxy
 */
@Slf4j
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class UserAuthServiceImpl implements UserAuthService {

    private final AdminMapper adminMapper;

    public UserAuthServiceImpl(AdminMapper adminMapper) {
        this.adminMapper = adminMapper;
    }

    public static UserAuthService me() {
        return SpringContextHolder.getBean(UserAuthService.class);
    }

    @TargetDataSource(value = DBTypeEnum.db1)
    @Override
    public Admin getAdminByAccount(String mobile) {
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", mobile);
        Admin admin = adminMapper.selectOne(queryWrapper);
        if (admin == null) {
            log.info("账号不存在");
            throw new CredentialsException("账号不存在");
        } else if (admin.getStatus() != 1) {
            log.info("账号被冻结");
            throw new LockedAccountException("账号被冻结");
        }
        return admin;
    }

    @TargetDataSource(value = DBTypeEnum.db2)
    @Override
    public ShiroUser getShiroAdmin(Admin admin) {
        ShiroUser shiroUser = ShiroKit.createShiroUser(admin);
        //用户角色数组
        Long[] roleArray = Convert.toLongArray(admin.getRoleList());

        //获取用户角色列表
        List<Long> roleList = new ArrayList<>();
        List<String> roleNameList = new ArrayList<>();
        for (Long roleId : roleArray) {
            roleList.add(roleId);
            roleNameList.add(ConstantFactory.me().getSingleRoleName(roleId));
        }
        shiroUser.setRoleList(roleList);
        shiroUser.setRoleNameList(roleNameList);
        return shiroUser;
    }

    @Override
    public AuthenticationInfo info(ShiroUser shiroUser, Admin admin, String name) {
        String credentials = admin.getPassword();
        String source = admin.getSalt();
        ByteSource credentialsSalt = new Md5Hash(source);
        return new SimpleAuthenticationInfo(shiroUser, credentials, credentialsSalt, name);
    }
}
